/**
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-01-17 10:59:16
 * @Description  : 通知接口控制器
 */
const { Op } = require('sequelize')
const Mysequelize = require('@/models')
const R = require('@/models/Response')
const { Notice, NoticeUser, User, UserDepartment } = require('@/models/model')
const { ERROR_USER_CODE, ERROR_SYSTEM_CODE } = require('@/constants/errorCode')
const { generatId } = require('@/utils/idUtil')
const { delModel, listModel, sortModel } = require('@/utils/controllerCommon')

/**
 * 列表查询通知接口
 * @param {*} ctx
 * @returns
 */
module.exports.listNotice = async (ctx) => {
  // const { type, isVisible } = ctx.query
  const whereCondition = {}
  // if (type) {
  //   whereCondition.type = +type
  // }
  // if (isVisible) {
  //   whereCondition.isVisible = +isVisible
  // }
  const orderCondition = [['sort']]
  await listModel(Notice)(ctx, whereCondition, orderCondition)
}

/**
 * 用户列表查询通知接口
 */
module.exports.listUserNotice = async (ctx) => {
  // 查询出所有通知，且是推送给当前用户的，且未读的
  const notices = await Notice.findAll({
    where: {
      sendTime: {
        [Op.lte]: Date.now()
      }
    },
    order: [['updateTime']]
  })

  const user = await User.findByPk(BigInt(ctx.user.id))

  const finaNotices = []

  for (let i = 0; i < notices.length; i++) {
    let auth = JSON.parse(notices[i].auth)
    // 看是否存在于指定部门
    const one = await UserDepartment.findOne({
      where: {
        userId: BigInt(user.id),
        departmentId: {
          [Op.in]: auth.depIds
        }
      }
    })

    if (
      +auth.all === 1 ||
      auth.userIds.includes(ctx.user.id) ||
      auth.roleIds.includes(user.roleId) ||
      one
    ) {
      // 并且为未读
      const isRead = await NoticeUser.findOne({
        where: {
          userId: BigInt(user.id),
          noticeId: notices[i].id,
          isRead: 1
        }
      })

      if (!isRead) {
        finaNotices.push(notices[i])
      }
    }
  }

  // 用户已经获取过这些列表了

  ctx.body = R.success(finaNotices)
}

/**
 * 用户已读接口
 */
module.exports.readNotice = async (ctx) => {
  const { noticeId } = ctx.request.body

  const one = await NoticeUser.findOne({
    where: {
      userId: BigInt(ctx.user.id),
      noticeId: BigInt(noticeId)
    }
  })

  try {
    if (one) {
      await NoticeUser.update(
        {
          isRead: 1
        },
        {
          where: {
            id: BigInt(one.id)
          }
        }
      )
    } else {
      const nextId = generatId()
      await NoticeUser.create({
        id: nextId,
        noticeId,
        userId: ctx.user.id,
        isRead: 0,
        createUser: ctx.user.id,
        updateUser: ctx.user.id
      })
    }
    ctx.body = R.success()
  } catch (error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.SYSTEM_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 更新通知对应的通知-用户
 * @param {*} userIds 通知-用户ID数组
 * @param {*} noticeId 通知ID
 * @param {*} userId 用户ID(操作人)
 * @param {*} t 事务对象
 */
const updateNoticeUser = async (userIds, noticeId, userId, t) => {
  for (let i = 0; i < userIds.length; i++) {
    const nextId = generatId()
    await NoticeUser.create(
      {
        id: nextId,
        noticeId,
        userId: userIds[i],
        isRead: 0,
        createUser: userId,
        updateUser: userId
      },
      {
        transaction: t
      }
    )
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 根据auth来获取对应的用户ID数组
 * @param {*} auth
 */
const getAuthUser = async (auth) => {
  let { all, depIds, roleIds, userIds } = auth
  if (all) {
    let users = await User.findAll({
      attributes: ['id']
    })
    users = users.map((item) => item.id)
    return users
  }

  // 不是all，集成depIds,roleIds,userIds的ID
  let resUsers = []
  // 集成部门内的用户
  depIds = depIds.map((v) => BigInt(v))
  let userDeps = await UserDepartment.findAll({
    attributes: ['userId'],
    where: {
      departmentId: {
        [Op.in]: depIds
      }
    }
  })
  userDeps = userDeps.map((item) => item.userId)

  // 集成role对应的用户
  roleIds = roleIds.map((v) => BigInt(v))
  let users2 = await User.findAll({
    attributes: ['id'],
    where: {
      roleId: {
        [Op.in]: roleIds
      }
    }
  })

  users2 = users2.map((item) => item.id)

  resUsers = resUsers.concat(userDeps, users2, userIds)
  resUsers = [...new Set(resUsers)]
  return resUsers
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 创建通知接口
 * @param {*} ctx
 */
module.exports.createNotice = async (ctx) => {
  const { name, content, type, sendTime, level, isActive, auth } =
    ctx.request.body

  const nextId = generatId()
  const sort = await Notice.max('sort')
  const t = await Mysequelize.transaction()
  let createObj = {
    id: nextId,
    name,
    content,
    type,
    level,
    isActive,
    sendTime,
    auth: JSON.stringify(auth),
    sort: sort + 1,
    createUser: ctx.user.id,
    updateUser: ctx.user.id
  }
  try {
    // 到这里可以进行通知的添加了,排序字段默认是最大值
    await Notice.create(createObj, {
      transaction: t
    })

    const userIds = await getAuthUser(auth)
    // 操作通知对应的通知-用户
    await updateNoticeUser(userIds, nextId, ctx.user.id, t)
    await t.commit()
    ctx.body = R.success()
  } catch (error) {
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.NOTICE_CREATE_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 更新通知接口
 * @param {*} ctx
 */
module.exports.updateNotice = async (ctx) => {
  const t = await Mysequelize.transaction()
  const { noticeId, name, content, sendTime, type, level, isActive, auth } =
    ctx.request.body
  const updateObj = {
    name,
    content,
    sendTime,
    level,
    isActive,
    type,
    auth: JSON.stringify(auth)
  }
  try {
    // 进行通知信息的更新
    await Notice.update(updateObj, {
      where: {
        id: BigInt(noticeId)
      },
      transaction: t
    })
    // 将此通知的通知-用户全部删除后，重新设置
    await NoticeUser.destroy({
      where: {
        noticeId: BigInt(noticeId)
      },
      transaction: t
    })

    const userIds = await getAuthUser(auth)
    await updateNoticeUser(userIds, noticeId, ctx.user.id, t)
    await t.commit()
    ctx.body = R.success()
  } catch (e) {
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.NOTICE_UPDATE_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 批量删除通知接口
 * @param {*} ctx
 */
module.exports.delNotices = async (ctx) => {
  await delModel(
    Notice,
    ERROR_USER_CODE.NOTICE_DEL_ERROR,
    'noticeIds'
  )(ctx, [{ model: NoticeUser, idName: 'noticeId' }])
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 通知排序接口
 * @param {*} ctx
 */
module.exports.sortNotices = async (ctx) => {
  // 传递的通知ID顺序即为排序顺序，取出这些ID对应的sort，sort从小到大排序后，依次赋值
  await sortModel(Notice, ERROR_USER_CODE.NOTICE_SORT_ERROR, 'noticeIds')(ctx)
}
